package com.wangxianseng.service;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.wangxianseng.bean.*;
import com.wangxianseng.file.CheckUtil;
import com.wangxianseng.file.FileUtil;
import com.wangxianseng.file.StringUtil;
import com.wangxianseng.utils.ExcelUtil;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

@Component
@Slf4j
public class ReadService {
    private List<String> types;
    private List<ConfigProp> configProps;
    private String folderPath;
    private String dependencyFilePath;
    private String resultFilePath;
    private ObjectMapper objectMapper = new ObjectMapper();

    //获取处理结果
    private  Map<String, List<Result>> getResult(ExportReq exportReq) {
        types = exportReq.getTypeFilters();
        folderPath = StringUtil.replaXg(exportReq.getFindFolderPath());
        resultFilePath = StringUtil.replaXg(exportReq.getResultFilePath());
        File folder = new File(folderPath);
        dependencyFilePath = StringUtil.replaXg(exportReq.getDependencyFilePath());
        this.configProps = FileUtil.getFindValueListByFile(dependencyFilePath);

        //递归获取所有文件的列表
        List<File> fileList = FileUtil.getAllFiles(folder);
        //过滤掉不符合要求的文件
        List<File> afterCheckFileList = fileList.stream().filter(x -> {
            //校验 文件格式
            return CheckUtil.checkFileName(types, x.getName());
        }).collect(Collectors.toList());

        try {
            List<Result> batch = batch(afterCheckFileList);
            Map<String, List<Result>> collect = batch.stream().collect(Collectors.groupingBy(Result::getFileName));
            return collect;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return (ConcurrentHashMap<String, List<Result>>) Collections.EMPTY_MAP;
    }

    //批量处理
    private List<Result> batch(List<File> fileList) throws InterruptedException {
        List<Result> resultList = new LinkedList<>();

        CountDownLatch latch = new CountDownLatch(fileList.size());

        for (File file : fileList) {
            new Thread(() -> {
                // 执行任务
                log.info(Thread.currentThread() +"读取 "+file.getName());
                List<Result> findValueList = doTask(file);
                resultList.addAll(findValueList);
                // 任务完成，计数器减1
                latch.countDown();
            }).start();
        }
        // 等待所有线程执行完毕
        latch.await();
        log.info("All threads have finished.");
        return resultList;
    }

    //逻辑处理
    private synchronized List<Result> doTask(File file) {
        List<Result> afterTask = new LinkedList<>();
        String fileName = file.getName();

        if (!file.isFile()) {
            return null;
        }
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            String line = null;
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if ("".equals(line)) continue;
                Iterator<ConfigProp> iterator = configProps.iterator();
                while (iterator.hasNext()) {
                    Result result = new Result();
                    ConfigProp configProp = iterator.next();
                    String customLine = configProp.getCustomLine();
                    if (Strings.isNotEmpty(customLine)){
                        if (!line.startsWith(customLine)) {
                            continue;
                        }
                    }
                    if (line.contains(configProp.getStartStr())) {
                        int i = line.indexOf(configProp.getStartStr());
                        String substring = line.substring(i);
                        String endChar = configProp.getEndChar();
                        String resultStr = "";
                        if (Strings.isBlank(endChar)) {
                            //到最后
                            resultStr = substring;
                        }else{
                            int i1 = substring.indexOf(endChar);
                            if (-1 == i1) {
                                resultStr = substring;
                            }else {
                                resultStr = substring.substring(0, i1);
                            }
                        }
                        String value = resultStr.substring(configProp.getStartStr().length());
                        result.setValue(value);
                        result.setFileName(fileName);
                        String filedName =  StringUtil.replaceFiledName(configProp.getStartStr());
                        result.setFieldName(filedName);
                        result.setLine(line);
                        result.setNeedCaculate(configProp.getNeedCaculate());
                        result.setSortNumber(configProp.getSortNumber());
                        afterTask.add(result);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 使用Collections.sort()进行排序
        Collections.sort(afterTask, (r1, r2) -> {
            return r1.getSortNumber().compareTo(r2.getSortNumber());
        });
        return afterTask;
    }

    public void export(ExportReq exportReq, HttpServletResponse response) {
        try {
            Map<String, List<Result>> result = getResult(exportReq);
            // 表头字段小写
            List<String> titleNames = new ArrayList<>();
            titleNames.add("文件名");
            //导出表头排序
            Collections.sort(configProps, (r1, r2) -> {
                return r1.getSortNumber().compareTo(r2.getSortNumber());
            });

            titleNames.addAll(configProps.stream().map(x->{
                String startStr = x.getStartStr();
                if (startStr.contains("=")) {
                    startStr = startStr.replace("=","");
                }
                return startStr;
            }).collect(Collectors.toList()));

            //表头
            List<String> excelHeader = new ArrayList<>(titleNames.size());
            List<String> excelHeaderParam = new ArrayList<>(titleNames.size());

            for (String titleName : titleNames) {
                if ("avg".equals(titleName)) {
                    excelHeaderParam.add("clat");
                    excelHeader.add("clat");
                } else if ("avg 平均值".equals(titleName)){
                    excelHeaderParam.add("clat 平均值");
                    excelHeader.add("clat 平均值");
                }else{
                    excelHeader.add(titleName);
                    excelHeaderParam.add(titleName);
                }
            }

            String[] arrString = excelHeader.toArray(new String[excelHeader.size()]);
            //填充表单数据
            List<Object[]> dataList = new ArrayList<>();


            if (!ObjectUtils.isEmpty(result)) {
                ArrayList<Object> datal = null;
                Set<Map.Entry<String, List<Result>>> entries = result.entrySet();
                for (Map.Entry<String, List<Result>> entry : entries) {
                    //文件名
                    String key = entry.getKey();
                    List<Result> resultList = entry.getValue();
                    Map dataMap = new HashMap();
                    dataMap.put("文件名",key);
                    for (Result result1 : resultList) {
                        //对象转map
                        dataMap.put(result1.getFieldName(), result1.getValue());
                        //avg 特殊处理
                        String fieldName = result1.getFieldName();
                        if ("avg".equals(fieldName)) {
                            String line = result1.getLine();
                            int startIndex = line.indexOf("(");
                            int endIndex = line.indexOf(")");
                            String unit = line.substring(startIndex-1, endIndex+1);
                            dataMap.put("clat", result1.getValue()+" "+unit);
                        }
                    }
                    datal = new ArrayList<>();
                    for (int i = 0; i < excelHeaderParam.size(); i++) {
                        Object obj = dataMap.get(excelHeaderParam.get(i));
                        if (!ObjectUtils.isEmpty(obj)){
                            String str = obj.toString();
                            datal.add(str);
                        }else {
                            datal.add(null);
                        }
                    }
                    Object[] array = datal.toArray(new String[excelHeader.size()]);
                    dataList.add(array);
                }
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            String time = sdf.format(new Date());
            String fileName = "文件结果" + time; //导出的excel的名称
            if (ObjectUtils.isEmpty(resultFilePath)) {
                ExcelUtil.exportExcel(response, fileName, arrString, dataList);
            }else{
                ExcelUtil.exportToLocalExcel(resultFilePath,fileName, arrString, dataList);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void exportExcelWithAvg(ExportReq exportReq, HttpServletResponse response) {
        try {
            Map<String, List<Result>> result = getResult(exportReq);
            List<ResultBO> customResult = getCustomResult(result);


            // 表头字段小写
            List<String> titleNames = new LinkedList<>();
            titleNames.add("截取文件名");
            titleNames.add("文件名");
            //导出表头排序
            Collections.sort(configProps, (r1, r2) -> {
                return r1.getSortNumber().compareTo(r2.getSortNumber());
            });

            titleNames.addAll(configProps.stream().map(x->{
                String startStr = x.getStartStr();
                if (startStr.contains("=")) {
                    startStr = startStr.replace("=","");
                }
                return startStr;
            }).collect(Collectors.toList()));
            for (ConfigProp configProp : configProps) {
                if (!ObjectUtils.isEmpty(configProp.getNeedCaculate())&&configProp.getNeedCaculate()) {
                    String startStr = configProp.getStartStr();
                    if (startStr.contains("=")) {
                        startStr = startStr.replace("=","");
                    }
                    if (startStr.equals("avg")){
                        titleNames.add("clat 平均值");
                    }else{
                        titleNames.add(startStr+" 平均值");
                    }
                }
            }

            //表头
            List<String> excelHeader = new ArrayList<>(titleNames.size());
            List<String> excelHeaderParam = new ArrayList<>(titleNames.size());

            for (String titleName : titleNames) {
                if ("avg".equals(titleName)) {
                    excelHeaderParam.add("clat");
                    excelHeader.add("clat");
                }else{
                    excelHeader.add(titleName);
                    excelHeaderParam.add(titleName);
                }
            }

            String[] arrString = excelHeader.toArray(new String[excelHeader.size()]);
            //填充表单数据
            List<Object[]> dataList = new ArrayList<>();

            Map<String, List<ResultBO>> collect = customResult.stream().collect(Collectors.groupingBy(ResultBO::getOriginFileName));

            if (!ObjectUtils.isEmpty(collect)) {
                ArrayList<Object> datal = null;
                Set<Map.Entry<String, List<ResultBO>>> entries = collect.entrySet();
                for (Map.Entry<String, List<ResultBO>> entry : entries) {
                    //文件名
                    String key = entry.getKey();
                    List<ResultBO> resultList = entry.getValue();
                    Map dataMap = new HashMap();

                    dataMap.put("截取文件名",resultList.get(0).getSubFileName());
                    dataMap.put("文件名",key);
                    for (ResultBO resultBO : resultList) {
                        if (!ObjectUtils.isEmpty(resultBO.getDoubleValue())&&!ObjectUtils.isEmpty(resultBO.getAvgValue())) {
                            if ("avg".equals(resultBO.getFieldName())) {
                                dataMap.put("clat 平均值", resultBO.getAvgValue()+" "+resultBO.getUnit());
                            }else {
                                dataMap.put(resultBO.getFieldName()+" 平均值", resultBO.getAvgValue()+" "+resultBO.getUnit());
                            }
                        }

                        //对象转map
                        dataMap.put(resultBO.getFieldName(), resultBO.getValue());
                        //avg 特殊处理
                        String fieldName = resultBO.getFieldName();
                        if ("avg".equals(fieldName)) {
                            String line = resultBO.getLine();
                            int startIndex = line.indexOf("(");
                            int endIndex = line.indexOf(")");
                            String unit = line.substring(startIndex-1, endIndex+1);
                            dataMap.put("clat", resultBO.getValue()+" "+unit);
                        }
                    }
                    datal = new ArrayList<>();
                    for (int i = 0; i < excelHeaderParam.size(); i++) {
                        Object obj = dataMap.get(excelHeaderParam.get(i));
                        if (!ObjectUtils.isEmpty(obj)){
                            String str = obj.toString();
                            datal.add(str);
                        }else {
                            datal.add(null);
                        }
                    }
                    Object[] array = datal.toArray(new String[excelHeader.size()]);
                    dataList.add(array);
                }
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            String time = sdf.format(new Date());
            String fileName = "文件结果" + time; //导出的excel的名称
            if (ObjectUtils.isEmpty(resultFilePath)) {
                ExcelUtil.exportAvgExcel(response, fileName, arrString, dataList);
            }else{
                ExcelUtil.exportToLocalExcel(resultFilePath,fileName, arrString, dataList);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private List<ResultBO> getCustomResult(Map<String, List<Result>> result) {
        List<ResultBO> resultBOArrayList = new ArrayList<>();
        // subName list
        Map<String, List<ResultBO>> sameFileNameMap = groupFileByTimes(result);

        Set<Map.Entry<String, List<ResultBO>>> entries = sameFileNameMap.entrySet();
        Iterator<Map.Entry<String, List<ResultBO>>> iterator = entries.iterator();
        //遍历分组后的map
        while (iterator.hasNext()) {
            Map.Entry<String, List<ResultBO>> next = iterator.next();
            List<ResultBO> value = next.getValue();
            for (ConfigProp configProp : configProps) {
                Boolean needCaculate = configProp.getNeedCaculate();
                if ((!ObjectUtils.isEmpty(needCaculate) && needCaculate)) {
                    getAvg(value, configProp);
                }
            }
            resultBOArrayList.addAll(value);
        }
        return resultBOArrayList;
    }

    private List<ResultBO> getAvg(List<ResultBO> resultBOList, ConfigProp configProp) {
        for (ResultBO resultBO : resultBOList) {
            String fieldValue = resultBO.getValue();
            String startStr = configProp.getStartStr();
            if (startStr.contains(resultBO.getFieldName())) {
                String afterSubValue = "";
                String sc = configProp.getSc();
                String ec = configProp.getEc();
                Boolean needCaculate = configProp.getNeedCaculate();
                //直接拿值 无前无后
                if (ObjectUtils.isEmpty(sc)&&ObjectUtils.isEmpty(ec)&& (!ObjectUtils.isEmpty(needCaculate)&&needCaculate)) {
                    afterSubValue = fieldValue;
                }
                //无 前 有后
                if (ObjectUtils.isEmpty(sc)&&!ObjectUtils.isEmpty(ec)) {
                    int i = fieldValue.indexOf(ec);
                    if (-1 == i) {
                        afterSubValue = fieldValue;
                    }else {
                        afterSubValue = fieldValue.substring(0, i);
                    }
                }
                //有前无后
                if (!ObjectUtils.isEmpty(sc)&&ObjectUtils.isEmpty(ec)) {
                    int i = fieldValue.indexOf(sc);
                    afterSubValue = fieldValue.substring(i);
                }
                //有前有后
                if ((!ObjectUtils.isEmpty(sc)&&!ObjectUtils.isEmpty(ec))&&(fieldValue.contains(sc)&& fieldValue.contains(ec))) {
                    int i = fieldValue.indexOf(sc);
                    String substring = fieldValue.substring(i);
                    String resultStr = "";
                    if (Strings.isBlank(ec)) {
                        //到最后
                        resultStr = substring;
                    }else{
                        int i1 = substring.indexOf(ec);
                        if (-1 == i1) {
                            resultStr = substring;
                        }else {
                            resultStr = substring.substring(0, i1-ec.length()+1);
                        }
                    }
                    afterSubValue = resultStr.substring(sc.length());
                }
                Double aDouble = null;
                try {
                    aDouble = Double.valueOf(afterSubValue);
                    resultBO.setDoubleValue(aDouble);
                } catch (NumberFormatException e) {
                    log.error("{} 该数据不是数值类型~",afterSubValue);
                }
                //特殊处理拿到实际单位
                if (resultBO.getFieldName().contains("BW")){
                    int i = fieldValue.indexOf("(");
                    int i1 = fieldValue.indexOf(")");
                    String unit = fieldValue.substring(i-1, i1+1);
                    resultBO.setUnit(unit);
                }else if (resultBO.getFieldName().contains("IOPS")){
                    if (fieldValue.contains("k")) {
                        resultBO.setUnit("k");
                    }
                }else if (resultBO.getFieldName().contains("avg")){
                    String line = resultBO.getLine();
                    int startIndex = line.indexOf("(");
                    int endIndex = line.indexOf(")");
                    String unit = line.substring(startIndex-1, endIndex+1);
                    resultBO.setUnit(unit);
                }else {
                    resultBO.setUnit(configProp.getUnit());
                }
            }
        }

        //fieldName
        Map<String, List<ResultBO>> collect = resultBOList.stream().collect(Collectors.groupingBy(ResultBO::getFieldName));
        Set<Map.Entry<String, List<ResultBO>>> entries = collect.entrySet();
        Iterator<Map.Entry<String, List<ResultBO>>> iterator = entries.iterator();

        while (iterator.hasNext()) {
            Map.Entry<String, List<ResultBO>> next = iterator.next();
            List<ResultBO> value = next.getValue();
            double sum = new Double(0);
            for (ResultBO resultBO : value) {
                Double doubleValue = resultBO.getDoubleValue();
                if ((!ObjectUtils.isEmpty(doubleValue))) {
                    sum += doubleValue;
                }
            }
            if (value.size()>1) {
                double avg = sum / value.size();
                for (ResultBO resultBO : value) {
                    resultBO.setAvgValue(avg);
                }
            }
        }

        return resultBOList;
    }

    //根据文件名分组
    private Map<String, List<ResultBO>> groupFileByTimes(Map<String, List<Result>> result) {
        List<ResultBO> resultBOList = new ArrayList<>();
        Collection<List<Result>> values = result.values();
        for (List<Result> value : values) {
            for (Result result1 : value) {
                ResultBO resultBO = new ResultBO();
                String fileName = result1.getFileName();
                if (fileName.contains("￥")) {
                    int i = fileName.indexOf("￥");
                    String substring = fileName.substring(i+1);
                    resultBO.setSubFileName(substring);
                }else {
                    resultBO.setSubFileName(fileName);
                }
                resultBO.setOriginFileName(fileName);
                BeanUtils.copyProperties(result1,resultBO);
                resultBOList.add(resultBO);
            }
        }
        Map<String, List<ResultBO>> collect = resultBOList.stream().collect(Collectors.groupingBy(ResultBO::getSubFileName));
        return collect;
    }

    //预览表格 带均值
    public List<Map<String, String>> preivewExcelWithAvg(ExportReq exportReq) {
        List<Map<String,String>> mapList = new LinkedList<>();
        try {
            Map<String, List<Result>> result = getResult(exportReq);
            List<ResultBO> customResult = getCustomResult(result);
            Map<String, List<ResultBO>> collect = customResult.stream().collect(Collectors.groupingBy(ResultBO::getOriginFileName));
            Set<Map.Entry<String, List<ResultBO>>> entries = collect.entrySet();
            Iterator<Map.Entry<String, List<ResultBO>>> iterator = entries.iterator();
            while (iterator.hasNext()) {
                Map<String, String> hashMap = new LinkedHashMap<>();
                Map.Entry<String, List<ResultBO>> next = iterator.next();
                String key = next.getKey();
                List<ResultBO> values = next.getValue();
                hashMap.put("截取文件名",values.get(0).getSubFileName());
                hashMap.put("文件名",key);
                if (!ObjectUtils.isEmpty(values)) {
                    HashMap<String, String> valuesMap = new LinkedHashMap<>();
                    for (ResultBO value : values) {
                        if ("avg".equals(value.getFieldName())) {
                            String line = value.getLine();
                            int startIndex = line.indexOf("(");
                            int endIndex = line.indexOf(")");
                            String unit = line.substring(startIndex-1, endIndex+1);
                            valuesMap.put("clat", value.getValue()+" "+unit);
                        }
                        else{
                            valuesMap.put(value.getFieldName(),value.getValue());
                        }
                        Double avgValue = value.getAvgValue();
                        if (!ObjectUtils.isEmpty(value.getDoubleValue())&&!ObjectUtils.isEmpty(avgValue)) {
                            if ("avg".equals(value.getFieldName())) {
                                valuesMap.put("clat 平均值",  String.format("%s  %s",value.getAvgValue(),ObjectUtils.isEmpty(value.getUnit())?"":value.getUnit()));
                            }else {
                                valuesMap.put(value.getFieldName()+" 平均值", String.format("%s  %s",value.getAvgValue(),ObjectUtils.isEmpty(value.getUnit())?"":value.getUnit()));
                            }
                        }
                    }
                    hashMap.putAll(valuesMap);
                }
                mapList.add(hashMap);
            }
        } catch (Exception e){
                throw new RuntimeException(e);
        }
        List<Map<String, String>> sortedMapList = mapList.stream()
                .sorted(Comparator.comparing((Map<String, String> m) -> m.get("截取文件名")))
                .collect(Collectors.toList());
        return sortedMapList;
    }

//    预览表格 不带均值
    public List<Map<String, String>> preivewExcel(ExportReq exportReq) {
        List<Map<String,String>> mapList = new ArrayList<>();
        try {
            Map<String, List<Result>> result = getResult(exportReq);
                Set<Map.Entry<String, List<Result>>> entries = result.entrySet();
                Iterator<Map.Entry<String, List<Result>>> iterator = entries.iterator();
                while (iterator.hasNext()) {
                    Map<String, String> hashMap = new LinkedHashMap<>();
                    Map.Entry<String, List<Result>> next = iterator.next();
                    String key = next.getKey();
                    hashMap.put("文件名",key);
                    List<Result> values = next.getValue();
                    if (!ObjectUtils.isEmpty(values)) {
                        HashMap<String, String> valuesMap = new LinkedHashMap<>();
                        for (Result value : values) {
                            if ("avg".equals(value.getFieldName())) {
                                String line = value.getLine();
                                int startIndex = line.indexOf("(");
                                int endIndex = line.indexOf(")");
                                String unit = line.substring(startIndex-1, endIndex+1);
                                valuesMap.put("clat", value.getValue()+" "+unit);
                            }
                            else{
                                valuesMap.put(value.getFieldName(),value.getValue());
                            }
                        }
                        hashMap.putAll(valuesMap);
                    }
                    mapList.add(hashMap);
                }
        } catch (Exception e){
            throw new RuntimeException(e);
        }
        return mapList;
    }

}
